/*
 * COSC603 ProjectOne
 * Software Testing and Maintenance
 * Sharda Rallabhandy
 */
package stutter;

import java.io.*;

import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;



// The Re-engineering of sutter.c
// This program checks for stuttered words in a file and writes them with the line number to another
/**
 * @version Using JRE ${p.get('java.version')}
 * @author Sharda Rallabhandy
 * <br>
 * COSC603 ProjectOne
 * <br>
 * Software Testing and Maintenance
 * <br>
 * 
 * 
 * <h1>
 * This program takes a filename as an argument and then scans the words to report any repeated (i.e., stuttered) words in a sentence.
 * </h1>
 * <br>
 * The Class Stutter
 */
public class Stutter {

	/**
	 * This program requires user input to specify the location of file to read and also where to write the output
	 */
	private String inputfile_;
	private String outputfile_;
	
	/**
	 * Gets the inputfile which was specified as the file to be read for stutter.
	 * 
	 * @return the inputfile specified incluiding path & fullname of the file
	 */
	public String getInputfile() {
		return inputfile_;
	}

	/**
	 * Sets the inputfile  which is specified as the file to be read for stutter.
	 * 
	 * @param inputfile
	 *            the new inputfile should be specified incluiding path & fullname of the file
	 */
	public void setInputfile(String inputfile) {
		this.inputfile_ = inputfile;
	}

	/**
	 * Gets the outputfile to which was specified to write the result for stutter.
	 * 
	 * @return the outputfile to be written incluiding path & fullname of the file.
	 */
	public String getOutputfile() {
		return outputfile_;
	}

	/**
	 * Sets the outputfile incluiding path & fullname of the file.
	 * 
	 * @param outputfile
	 *            the new outputfile to which is specified to write the result for stutter incluiding path & fullname of the file.
	 */
	public void setOutputfile(String outputfile) {
		this.outputfile_ = outputfile;
	}

	/**
	 * The main method.
	 * 
	 * @param args
	 *            the arguments
	 *            This code runs creates an instance of stutter and passes the file to be read 
	 *            and gets the output as specified location.
	 */

	public static void main(String[] args) {
		
		// The code is surrounded by try-catch block to catch any exceptions
		// encountered during execution
		try {
		//create a new instance of stutter	
		Stutter stutter = new Stutter();
		
		//set the input file location
		stutter.setInputfile("C:\\stutter.txt");
		//set the output file location
		stutter.setOutputfile("C:\\output.txt");
		
		//run the code to generate the output
		stutter.runStutter(stutter);
		}
		
		// The exceptions are caught here
		catch (Exception e) {
			// All kinds of exceptions are caught here 
			System.err.println("Error: " + e.getMessage());
			
			// Print the error trace
			e.printStackTrace();
		}
	}
	
	/**
	 * Run stutter.
	 * 
	 * @param stutter
	 *            the stutter is an object of class Stutter
	 * @throws Exception
	 *             the exception which can be any kind
	 */
	public void runStutter(Stutter stutter) throws Exception{
		// Set the initial variables
		int line = 0;
		Boolean isEndOfSentence;
		String readline, firstWord = null, nextWord;

		BufferedReader reader = (BufferedReader) stutter
				.getFileBufferedReader(stutter.getInputfile());
		BufferedWriter writer = (BufferedWriter) stutter
				.getFileBufferedWriter(stutter.getOutputfile());

		// while the file has data in it read line by line
		while ((readline = reader.readLine()) != null) {
			// incrementing the line counter after done with reading a line
			line++;

			// Tokenize the read string by space so that we get separate
			// words
			StringTokenizer wordTokens = new StringTokenizer(readline);

			// while there are words in the read line get word by word
			while (wordTokens.hasMoreTokens()) {
				nextWord = wordTokens.nextToken();
				@SuppressWarnings("unchecked")
				List<Object> checkForEndOfSentence = (List<Object>) stutter
						.checkForEndOfSentence(nextWord);

				nextWord = (String) checkForEndOfSentence.get(0);
				isEndOfSentence = (Boolean) checkForEndOfSentence.get(1);

				// Compare the two subsequent words on a sentence or phrase
				if (firstWord != null
						&& firstWord.equalsIgnoreCase(nextWord)) {
					System.out.println("Repeated word on line " + line
							+ ": " + firstWord + " " + nextWord);
					writer.write("Repeated word on line " + line + ": "
							+ firstWord + " " + nextWord);
					writer.newLine();
				}

				// If at all a punctuation mark is encountered reset the
				// counter
				if (isEndOfSentence) {
					firstWord = null;
				} else {
					//else assign second word to first word and proceed to read next word
					firstWord = nextWord;
				}
			}
		}
		// Close the output file
		writer.close();
		// Close the input file
		reader.close();
	}

	/**
	 * Gets the file buffered reader for a specified file location.(Ex. C:\\stutter.txt)
	 * 
	 * @param filelocation
	 *            the filelocation including the name of the file
	 * @return the file buffered reader so that the file can be read line by line
	 * @throws FileNotFoundException
	 *             the file not found exception is thrown if the specified input file is not accessible
	 */
	private Object getFileBufferedReader(String fileLocation)
			throws FileNotFoundException {
		// opens and reads the file stutter.txt
		// The location of the stutter.txt should be in "C:\\" drive
		FileInputStream fileInputStream = new FileInputStream(fileLocation);
		DataInputStream dataInputStream = new DataInputStream(fileInputStream);
		BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(dataInputStream));

		return bufferedReader;
	}

	/**
	 * Gets the file buffered writer to write the output of the caller.
	 * 
	 * @param filelocation
	 *            the filelocation where the output is desired, including the name of the file
	 * @return the file buffered writer is returned to the caller to write to the file
	 * @throws IOException
	 *             Signals that an I/O exception has occurred, and is thrown when the specified output location is not accessible.
	 */
	private Object getFileBufferedWriter(String fileLocation) throws IOException {
		// opens the file output.txt to write the result
		// The output file is written at location "C:\\"
		FileWriter outStream = new FileWriter(fileLocation);
		BufferedWriter bufferedWriter = new BufferedWriter(outStream);

		return bufferedWriter;
	}

	/**
	 * Check for end of sentence, i.e., whether the word has any punctuation mark attached to it.
	 * 
	 * @param givenWord
	 *            the 'givenWord' is the input word for this method, for which the desired check is performed
	 * @return the object which has list of two objects, first one a string without punctuation mark, 
	 * second object is a boolean value indication whether a punctuation mark was attached earlier.
	 */
	private Object checkForEndOfSentence(String givenWord) {
		// The punctuation marks are checked for while reading the words
		final String[] PUNCTUATION_MARK = { ",", ".", "!", ";", "?", ":" };
		Boolean isEndOfSentence = false;
		List<Object> checkForEndOfSentence = new ArrayList<Object>();
		for (int k = 0; k < PUNCTUATION_MARK.length; k++) {
			if (givenWord.contains(PUNCTUATION_MARK[k])) {
				givenWord = givenWord.substring(0, givenWord.indexOf(PUNCTUATION_MARK[k]));
				isEndOfSentence = true;
			}
		}
		checkForEndOfSentence.add(0, givenWord);
		checkForEndOfSentence.add(1, isEndOfSentence);

		return checkForEndOfSentence;

	}
}
